var _ = require('underscore');
var urllib = require('urllib');
var moment = require('moment');
var crypto = require('crypto')
var Decimal = require('decimal.js');

const { appid } = require('../../server_config.json').wechat;

var MathNum = function (len) {
    Math.floor(Math.random() * 10);
    let rnum = '';
    for (let i = 0; i < len; i++) {
        rnum += Math.floor(Math.random() * 10);
    }
    return rnum;
}

var MathCode = function () {
    let rcode = '';
    let dtcode = new Date().getTime() + '';
    let mcode = MathNum(6);
    rcode = dtcode.substring(dtcode.length - 6) + mcode;
    return rcode;
}

var formatSqlObj = function (data) {
    let id = data.id;
    let cols = _.keys(_.omit(data, 'id'));
    let vals = _.values(_.omit(data, 'id'));
    let fmt = _.map(cols, function (item) {
        return '?';
    })
    return {
        cols, vals, fmt, id
    }
}

var initObj = function (mod, data) {
    let doc = {};
    let msg = '';
    for (const key in mod) {
        if (Object.hasOwnProperty.call(mod, key)) {
            const item = mod[key];
            if (data[key] || data[key]==0) {
                if (item.type == 'string') {
                    if (data[key].length > item.length) {
                        msg = `${item.name}长度超限`;
                        break;
                    } else {
                        doc[key] = data[key];
                    }
                } else if(item.type == 'number'){
                    try {
                        if(!isNaN(Number(data[key]))){
                            doc[key] = data[key];
                        }else{
                            msg = `${item.name}类型不匹配`;
                            break;
                        }
                    } catch (error) {
                        msg = `${item.name}类型不匹配`;
                        break;
                    }
                } else {
                    doc[key] = data[key];
                }
            } else {
                if (Object.hasOwnProperty.call(item, 'default')) {
                    doc[key] = item.default;
                }
            }
        }
    }
    doc['createtime'] = new Date();
    doc['updatetime'] = new Date();
    if (msg) {
        throw new Error(msg);
    } else {
        return doc;
    }
}

var formatObj = function (mod, data) {
    let doc = {};
    let msg = '';

    for (const key in data) {
        if (Object.hasOwnProperty.call(data, key)) {
            const item = mod[key];
            if (key == 'id') {
                doc[key] = data[key];
                continue;
            }
            if (item) {
                if (item.type == 'string') {
                    if (data[key] && data[key].length > item.length) {
                        msg = `${item.name}长度超限`;
                        break;
                    } else {
                        doc[key] = data[key];
                    }
                } else if(item.type == 'number'){
                    try {
                        if(!isNaN(Number(data[key]))){
                            doc[key] = data[key];
                        }else{
                            msg = `${item.name}类型不匹配`;
                            break;
                        }
                    } catch (error) {
                        msg = `${item.name}类型不匹配`;
                        break;
                    }
                } else {
                    doc[key] = data[key];
                }
            }
        }
    }
    doc['updatetime'] = new Date();
    if (msg) {
        throw new Error(msg);
    } else {
        return doc;
    }
}

var filterObj = function (mod, data) {
    let filter = {};
    for (const key in data) {
        if (Object.hasOwnProperty.call(data, key)) {
            const element = data[key];
            if (element != '') {
                if (mod[key] || key == 'id') {
                    filter[key] = element;
                }
            }
        }
    }
    return filter;
}

// 随机字符串产生函数  
var createtokenStr = function () {
    return Math.random().toString(36);
};

// 加密数据
let secretKey = '361280e958964e23'; //goeasy-secretKey
var encryptedData = function (algorithm, content) {
    try {
        const hash = crypto.createHmac(algorithm, secretKey)
            .update(content)
            .digest('base64');
            return hash
    } catch (error) {
        console.log('=--------encryptedData----error',error)
        return '';
    }
}

// 解密数据
var decryptData = function (sessionkey, encryptedData, iv) {
    try {
        var decoded;
        sessionKey = new Buffer(sessionkey, 'base64');
        encryptedData = new Buffer(encryptedData, 'base64');
        iv = new Buffer(iv, 'base64');
        // 解密
        var decipher = crypto.createDecipheriv('aes-128-cbc', sessionKey, iv);
        // 设置自动 padding 为 true，删除填充补位
        decipher.setAutoPadding(true);
        decoded = decipher.update(encryptedData, 'binary', 'utf8');
        decoded += decipher.final('utf8');

        decoded = JSON.parse(decoded)
        if (decoded.watermark.appid !== appid) {
            console.log('appid不匹配');
            throw new Error('appid不匹配')
        }
        delete decoded.watermark
        return decoded;
    } catch (err) {
        console.log('解密第一次');
        console.log(err);
        throw new Error('解密失败')
    }
}

var formatDate = function (datestr) {
    return datestr ? moment(datestr).format('YYYY-MM-DD') : null;
}
var formatDateTime = function (datestr) {
    return datestr ? moment(datestr).format('YYYY-MM-DD HH:mm') : null;
}
var formatDateYear = function (datestr) {
    let datas =  datestr ? moment(datestr).format('YY-MM-DD'): null;
    if(datas){
        let ds = datas.split('-');
        return ds[0]+'年';
    }else{
        return '';
    }
}
var formatDateYearMonth = function (datestr) {
    let datas =  datestr ? moment(datestr).format('YY-MM-DD'): null;
    if(datas){
        let ds = datas.split('-');
        return ds[0]+'年'+Number(ds[1])+'月';
    }else{
        return '';
    }
}
// 星座
const getStar = function (birthday) {
    let star = '白羊座';
    let month = (new Date(birthday)).getMonth() + 1;
    let day = (new Date(birthday)).getDate();
    if (month == 3) {
        if (day < 21) {
            star = '双鱼座';
        } else {
            star = '白羊座';
        }
    } else if (month == 4) {
        if (day < 20) {
            star = '白羊座';
        } else {
            star = '金牛座';
        }
    } else if (month == 5) {
        if (day < 21) {
            star = '金牛座';
        } else {
            star = '双子座';
        }
    } else if (month == 6) {
        if (day < 22) {
            star = '双子座';
        } else {
            star = '巨蟹座';
        }
    } else if (month == 7) {
        if (day < 23) {
            star = '巨蟹座';
        } else {
            star = '狮子座';
        }
    } else if (month == 8) {
        if (day < 23) {
            star = '狮子座';
        } else {
            star = '处女座';
        }
    } else if (month == 9) {
        if (day < 23) {
            star = '处女座';
        } else {
            star = '天秤座';
        }
    } else if (month == 10) {
        if (day < 24) {
            star = '天秤座';
        } else {
            star = '天蝎座';
        }
    } else if (month == 11) {
        if (day < 23) {
            star = '天蝎座';
        } else {
            star = '射手座';
        }
    } else if (month == 12) {
        if (day < 22) {
            star = '射手座';
        } else {
            star = '摩羯座';
        }
    } else if (month == 1) {
        if (day < 20) {
            star = '摩羯座';
        } else {
            star = '水瓶座';
        }
    } else if (month == 2) {
        if (day < 19) {
            star = '水瓶座';
        } else {
            star = '双鱼座';
        }
    }
    return star;
};
// 年龄
const getAge = function (birthday) {
    let age = Math.floor((new Date().getTime() - new Date(birthday).getTime()) / (1000 * 3600 * 24 * 365));
    return age < 1 ? 1 : age;
}

async function requestGet(url) {
    return new Promise(function (resolve, reject) {
        urllib.request(url, { dataType: 'json' }, function (err, data) {
            if (err) {
                reject(err)
            } else {
                resolve(data)
            }
        })
    });
}
async function requestPost(url, body) {
    return new Promise(function (resolve, reject) {
        urllib.request(url, { dataType: 'json', method: 'POST', data: body }, function (err, data) {
            if (err) {
                reject(err)
            } else {
                resolve(data)
            }
        })
    });
}
class Wxpay {
    //把金额转为分
    getmoney(money) {
        return new Decimal(money).mul(new Decimal(100)).toNumber();
    }
    /** 相加 */
    add(num1, num2) {
        return new Decimal(num1).add(new Decimal(num2)).toNumber().toFixed(2);
    }
    /** 相减 */
    sub(num1, num2) {
        return new Decimal(num1).sub(new Decimal(num2)).toNumber().toFixed(2);
    }
    /** 乘法 */
    mul(num1, num2) {
        return new Decimal(num1).mul(new Decimal(num2)).toNumber().toFixed(2);
    }
    /** 除法 */
    div(num1, num2) {
        return new Decimal(num1).div(new Decimal(num2)).toNumber().toFixed(2);
    }

    // 随机字符串产生函数  
    createNonceStr() {
        return Math.random().toString(36).substr(2, 15);
    };

    // 时间戳产生函数  
    createTimeStamp() {
        return parseInt(new Date().getTime() / 1000 + '');
    }

    //签名加密算法
    paysignjsapi(appid, body, mch_id, nonce_str, notify_url, openid, out_trade_no, spbill_create_ip, total_fee, trade_type, mchkey) {
        var ret = {
            appid: appid,
            mch_id: mch_id,
            nonce_str: nonce_str,
            body: body,
            notify_url: notify_url,
            openid: openid,
            out_trade_no: out_trade_no,
            spbill_create_ip: spbill_create_ip,
            total_fee: total_fee,
            trade_type: trade_type
        };
        console.log('ret==', ret);
        var string = this.raw(ret);
        var key = mchkey;
        string = string + '&key=' + key;
        console.log('string=', string);
        return crypto.createHash('MD5').update(string, 'utf8').digest('hex').toUpperCase();
    }
    //签名加密算法,第二次的签名
    paysignjsapifinal(appid, mch_id, prepayid, noncestr, timestamp, mchkey, total_fee) {
        var ret = {
            appId: appid,
            nonceStr: noncestr,
            package: `prepay_id=${prepayid}`,
            signType: 'MD5',
            //partnerid: mch_id,
            //prepayid: prepayid,
            //package: 'Sign=WXPay',
            //noncestr: noncestr,
            timeStamp: timestamp//,
            //total_fee: total_fee
        };
        //console.log('retretret==', ret);
        var string = this.raw(ret);
        var key = mchkey;
        string = string + '&key=' + key;
        console.log('二次签名=', string);
        return crypto.createHash('MD5').update(string, 'utf8').digest('hex').toUpperCase();
    }
    //签名加密算法
    makesign(ret, mchkey) {
        var string = this.raw(ret);
        var key = mchkey;
        string = string + '&key=' + key;
        console.log('签名=', string);
        return crypto.createHash('MD5').update(string, 'utf8').digest('hex').toUpperCase();
    }
    raw(args) {
        var keys = Object.keys(args);
        keys = keys.sort()
        var newArgs = {};
        keys.forEach(function (key) {
            newArgs[key] = args[key];
        });
        var string = '';
        for (var k in newArgs) {
            string += '&' + k + '=' + newArgs[k];
        }
        string = string.substr(1);
        return string;
    }

    json2Xml(json) {
        let _xml = '';
        Object.keys(json).map((key) => {
            _xml += `<${key}>${json[key]}</${key}>`
        })
        return `<xml>${_xml}</xml>`;
    }

}
module.exports = {
    MathNum,
    MathCode,
    formatSqlObj,
    initObj,
    formatObj,
    filterObj,
    createtokenStr,
    encryptedData,
    decryptData,
    requestGet,
    requestPost,
    formatDate,
    formatDateTime,
    formatDateYear,
    formatDateYearMonth,
    getStar,
    getAge,
    wxpay: new Wxpay()
}